def scree_plot(X, max_components=None, save=True):
    """
    Plot a scree plot (explained variance ratio per component) and
    the cumulative explained variance.

    Parameters
    ----------
    X : array-like, shape (n_samples, n_features)
        Data matrix.
    max_components : int or None
        Maximum number of components to compute/plot. Defaults to
        min(n_samples, n_features).
    save : bool
        If True, calls plt.savefig() at the end to save the figure.
    """
    n_components = min(X.shape[0], X.shape[1])
    if max_components is not None:
        n_components = min(n_components, int(max_components))

    pca_full = PCA(n_components=n_components, svd_solver="full", random_state=0)
    pca_full.fit(X)

    var_ratio = pca_full.explained_variance_ratio_
    cum_var = np.cumsum(var_ratio)
    idx = np.arange(1, len(var_ratio) + 1)

    plt.figure(figsize=(7, 4.5))
    # per-component variance
    plt.plot(idx, var_ratio, marker="o", linewidth=1)
    # cumulative variance
    plt.plot(idx, cum_var, linestyle="--", marker="s", linewidth=1)
    plt.xticks(idx)
    plt.xlabel("Principal Component")
    plt.ylabel("Explained variance ratio")
    plt.title("Scree plot")
    plt.grid(True, alpha=0.3)
    plt.legend(["Per-component", "Cumulative"], loc="best")
    plt.show()

    return {
        "explained_variance_ratio": var_ratio,
        "cumulative_explained_variance": cum_var,
        "pca": pca_full,
    }